﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Utilities
{
   public partial class LoggerView : UserControl
   {
      private static Logger logger_ = new Logger();
      private LoggerPipe.HasMessagesEventHandler eventHandler;

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      public LoggerView()
      {
         InitializeComponent();
         eventHandler = new LoggerPipe.HasMessagesEventHandler(HandleMessagesEvent);
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      public void Shutdown()
      {
         try
         {
            LoggerPipe.hasMessagesEvent -= eventHandler;
         }
         catch (System.Exception ex)
         {
            logger_.Exception(ex);
         }
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void HandleResize(object sender, EventArgs e)
      {
         ListView view = sender as ListView;
         try
         {
            view = sender as ListView;
            if (null == view)
            {
               return;
            }
            view.BeginUpdate();

            int count = (null == view) ? 0 : view.Columns.Count;
            if (0 == count)
            {
               // Not ready
               return;
            }

            // Size the right-most column as large as possible
            if (0 < count)
            {
               int remaining = view.ClientSize.Width;
               if (1 < count)
               {
                  remaining -= view.Columns.Cast<ColumnHeader>()
                     .Take(count - 1).Sum(column => column.Width);
               }
               view.Columns[count - 1].Width = Math.Max(40, remaining);
            }
         }
         catch (System.Exception ex)
         {
            logger_.Exception(ex);
         }
         finally
         {
            if (null != view)
            {
               view.EndUpdate();
            }
         }
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void LoggerView_Load(object sender, EventArgs e)
      {
         try
         {
            lvMessage.Dock = DockStyle.Fill;
            LoggerPipe.hasMessagesEvent += eventHandler;
         }
         catch (System.Exception ex)
         {
            logger_.Exception(ex);
         }
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      void HandleMessagesEvent(object sender, EventArgs e)
      {
         try
         {
            SafeAsyncInvoker.BeginInvoke(lvMessage, () =>
            {
               try
               {
                  lvMessage.BeginUpdate();

                  // Drop excess messages
                  int itemCount = lvMessage.Items.Count;
                  if (0 < itemCount)
                  {
                     int readCount = Math.Min(1000, LoggerPipe.Count);
                     int deleteCount = Math.Max(0, (itemCount + readCount) - 1000);
                     while (0 < deleteCount--)
                     {
                        lvMessage.Items.RemoveAt(--itemCount);
                     }
                  }

                  // And insert new ones
                  LoggerPipe.LoggingEvent loggingEvent;
                  while (LoggerPipe.Read(out loggingEvent))
                  {
                     string message = loggingEvent.RenderedText;
                     string timestamp = loggingEvent.Timestamp.ToString("HH:mm:ss.fff");
                     ListViewItem item = lvMessage.Items.Insert(0, timestamp);
                     item.SubItems.Add(message);

                     // Set the colour according to the level
                     item.BackColor = loggingEvent.BackColor;
                     item.ForeColor = loggingEvent.ForeColor;
                  }
               }
               finally
               {
                  lvMessage.EndUpdate();
               }
            });
         }
         catch (System.Exception)
         {
            // Cannot output an exception, as we are inside the logger
            // and it would recurse
         }
      }
   }
}
